<?php

namespace app\divination\controller;

use app\aliyun\controller\AliyunFilterWord;
use app\common\cachemodel\ZlTarotRecords;
use app\common\lib\astrolog\Astrolog;
use app\common\lib\exception\ApiException;
use app\common\lib\Util;
use app\common\model\AstroSettingUser1751;
use app\common\model\Divination;
use app\common\model\DivinationNote;
use app\common\model\DivinationSabienTips;
use app\common\model\DivinationTips;
use app\check\controller\Check;
use think\Cache;
use think\Db;
use think\Log;
use think\response\Json;

/**
 * Class Index
 * @title 提问接口
 * @url  /divination/
 * @desc  提问相关接口
 * @version 1.0.0
 * @readme /doc/md/divination/index.md
 */
class Index extends Check
{
    //开启授权认证
    public $apiAuth = false;
    protected $restActionList = ['get', 'delete',];
    //附加方法
    protected $extraActionList = ['history', 'dice', 'specialty', 'divination'];
    //跳过鉴权的方法
    protected $skipAuthActionList = [];

    /**
     * @title 开始提问 兼容V10
     * @method POST
     * @param array $paramsMap 内部调用传参
     * @return int|json did 提问记录id
     * @throws ApiException
     * @readme /doc/md/divination/get.md
     */
    public function get($paramsMap = [])
    {
        $data['question'] = htmlspecialchars(trim($paramsMap['question'] ?? input('question')));

        if (strlen($data['question']) == 0) throw new ApiException('请输入问题，再进行提问');


        $aliRes = AliyunFilterWord::checkText($data['question']);
        if ($aliRes)
        {
            return show(0, '检测到敏感内容');
        }

        $data['uid'] = $paramsMap['uid'] ?? $this->user['id'];

        $data['timezone'] = $paramsMap['timezone'] ?? input('timezone');// 时区
        $data['longitude'] = $paramsMap['longitude'] ?? input('longitude');// 经度
        $data['latitude'] = $paramsMap['latitude'] ?? input('latitude');// 纬度
        $data['tag_id'] = $paramsMap['tag_id'] ?? input('tag_id/d', 0);// 指定类型

        $validate = validate('DivinationIndex');

        if ($validate->check($data) !== true)
        {
            Log::write('提问错误:' . $validate->getError(), 'error_divination', true);
            return show(config('code.error'), (string)$validate->getError());
        }

        // 安卓端在塔罗开发版本时，纬度和时区字段两个值传反了，特殊处理
        if ($this->request->header('app-type') === 'android'
            && Util::CheckAppVersion('2.7.2') === '小'
            && Util::CheckAppVersion('2.5.0') !== '小')
        {
            $tmp = $data['latitude'];
            $data['latitude'] = $data['longitude'];
            $data['longitude'] = $data['timezone'];
            $data['timezone'] = $tmp;
        }

        $_arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 16];// 行星id随机数种子

        $data['planet'] = $_arr[rand(0, count($_arr) - 1)];
        $data['sign'] = rand(1, 12);
        $data['house'] = rand(1, 12);
        $data['deg'] = round(randomFloat(0, 29), 8);
        $data['create_time'] = time();

        try
        {
            $id = Divination::insertGetId($data);
            Cache::rm(Divination::REDIS_KEY_IDS . $data['uid']);
        }
        catch (\Exception $e)
        {
            Log::write('提问入库失败:' . $e->getMessage(), 'divination_error', true);
            return show(config('code.error'), '请稍后重试');
        }
        // 内部调用时返回
        if (!empty($paramsMap))
        {
            return $id;
        }

        return show(config('code.success'), '加载成功', ['did' => (int)($id), 'time' => $data['create_time']]);
    }

    /**
     * @title 提问历史记录
     * @method GET
     * @return int id
     * @return string question 问题
     * @return int sign 星座1~2
     * @return int house 宫位1~12
     * @return int planet 行星id 0,1,2,3,4,5,6,7,8,9,12,16
     * @return int deg 度数
     * @return int create_time 提问时间 时间戳（秒为单位）
     * @readme /doc/md/divination/history.md
     * @return \think\Response|\think\response\Json|\think\response\Jsonp|\think\response\Redirect|\think\response\Xml
     */
    public function history()
    {
        $uid = $this->user['id'];

        $page = input('page/d', 1);

        $is_use_cache = 1;
        if ($is_use_cache)
        {
            $map['page'] = $page;
            $map['uid'] = $uid;

            try
            {
                $data = (new Divination())->getListPage($map);
                if (isset($data['data']) && !empty($data['data']))
                {
                    return show(200, '成功', $data);
                } else
                {
                    return show(200, '您的提问记录为空，立即去提问吧~', $data);
                }
            }
            catch (\Exception $e)
            {
                Log::write('获取提问历史记录失败' . $e->getMessage() . var_export(request()->param(), true), 'error', true);

                return show(config('code.error'), '网络错误');
            }

        } else
        {
            try
            {
                $total = Divination::where('uid', $uid)
                    ->count('id');

                $data = getPaginatorData($total, $page);

                if ((int)($total) > 0)
                {
                    $data['data'] = Divination::field('id,question,planet,sign,house,create_time')
                        ->where('uid', $uid)
                        ->order('id desc')
                        ->limit($data['start'], $data['end'])
                        ->select();

                    unset($data['start']);
                    unset($data['end']);
                }
            }
            catch (\Exception $e)
            {
                Log::write('提问历史查询失败' . $e->getMessage(), 'divination_error', true);
                return show(config('code.error'), '加载失败');
            }

            if ($total > 0)
            {
                return show(200, '成功', $data);
            } else
            {
                return show(200, '您的提问记录为空，立即去提问吧~', $data);
            }
        }

    }

    /**
     * @title 删除提问历史
     * @method DELETE
     * @param int $did 记录id
     * @readme /doc/md/divination/delete.md
     * @return \think\Response
     */
    public function delete($did)
    {
        $uid = (int)($this->user['id']);

        if ($did <= 0 || $uid <= 0)
        {
            return show(config('code.error'), '参数错误');
        }
        $Divination = new Divination();
        // 获取提问详情
        $dice = $Divination->getDetail(['id' => $did]);
        // 若未查询到数据，则返回错误信息
        if ($dice === false || $dice['is_del'] == 1 || $dice['uid'] != $uid)
        {
            return show(config('code.error'), '数据不存在');
        }
        Divination::update(['is_del' => 1], ['uid' => $uid, 'id' => $did]);
        Cache::rm(Divination::REDIS_KEY_IDS . $uid);
        Cache::rm(Divination::REDIS_KEY_DETAIL . $did);

        return show(config('code.success'), '删除成功');
    }

    /**
     * @title 骰子经典模式 v10兼容
     * @method GET
     * @return Json
     * @return int time 提问时间 时间戳/秒
     * @return int planet 行星id
     * @return int house 行星id
     * @return int sign 行星id
     * @return string love_status 骰子爱情状态
     * @return string marital_status 骰子婚姻状态 暂时去掉
     * @return string health_status 骰子健康状态
     * @return string trip_status 骰子出行状态
     * @return string money_status 骰子财富状态
     * @return string career_status 骰子事业状态
     * @return string study_status 骰子学业状态
     * @return string planet_text 骰子行星词条
     * @return string house_text 骰子宫位词条
     * @return string|Json sign_text 骰子星座词条
     * @return \think\Response|\think\response\Json|\think\response\Jsonp|\think\response\Redirect|\think\response\Xml
     * @readme /doc/md/divination/dice.md
     */
    public function dice($paramsMap = [])
    {
        $did = $paramsMap['did'] ?? (int)(input('did'));
        $uid = (int)($this->user['id']);

        if ($did <= 0 || $uid <= 0)
        {
            return show(config('code.error'), '参数错误');
        }

        $Divination = new Divination();
        // 获取提问详情
        $dice = $Divination->getDetail(['id' => $did]);
        // 若未查询到数据，则返回错误信息
        if ($dice === false || $dice['uid'] != $uid)
        {
            return show(config('code.error'), '数据不存在');
        }

        // 计算骰子六种模式
        $dice_status = $this->diceStatus($dice['planet'], $dice['sign'], $dice['house'], $dice['deg']);

        $customer_service = (new ZlTarotRecords())->getCustomService();
        $aiAnswer = (new ZlTarotRecords())->getAiAnswer(1, $dice);
        $result = [
            'did' => $dice['id'],
            'planet' => $dice['planet'],
            'house' => $dice['house'],
            'sign' => $dice['sign'],
            'love_status' => $dice_status['love'],
            'health_status' => $dice_status['health'],
            'trip_status' => $dice_status['trip'],
            'money_status' => $dice_status['money'],
            'career_status' => $dice_status['career'],
            'study_status' => $dice_status['study'],
            'customer_service' => $customer_service,
            'ai_answer' => $aiAnswer
        ];

        //根据提问详情获取骰子词条
        $DivinationTips = new DivinationTips();
        $result['planet_text'] = $DivinationTips->getDetail('p-' . $dice['planet']);
        $result['sign_text'] = $DivinationTips->getDetail('s-' . $dice['sign']);
        $result['house_text'] = $DivinationTips->getDetail('h-' . $dice['house']);
        // 内部调用时
        if (!empty($paramsMap))
        {
            return $result;
        }

        $result['tag_id'] = $dice['tag_id'] ?? ''; // v10版本 指定类型兼容
        $result['time'] = $dice['create_time'];
//        $result['url'] = 'https://weidian.com/item.html?itemID=2552906806';// 微店链接
//        $result['url'] = 'https://weidian.com/item.html?itemID=4475663455';// 微店链接（由于 微店问题，先改为这个地址，未来 改为 原地址【因为老的地址有评价】）
//        $result['url'] = 'https://weidian.com/item.html?itemID=4479316612';// 微店链接（由于原来的骰子，微店不能有迷信的产品，所以改为了这个）
//        $result['url'] = 'https://oss.goddessxzns.com/app/dice_ask.jpg';// 微店被封了，先替换为联系微信的，【改为草料活码，不好使，转到oss里refer失败】
//        $result['url'] = 'https://qr34.cn/EGF7t4';// 上面的操作，安卓的webview不能直接加载图片
        $result['url'] = 'https://wechat.goddessxzns.com/web/dice_ask/index.html';// 安卓跳两下，写死

        return show(config('code.success'), '加载成功', $result);

//        try
//        {
//            $is_use_cache = 1;
//            if ($is_use_cache)
//            {
//
//
//                // TODO 处理$dice 未查询到数据的问题
//
//
//            } else
//            {
//                $dice = Divination::field('id,question,planet,sign,house,deg,create_time')->where('uid', $uid)->findOrFail($did);
//                // 骰子词条
//                $tips = DivinationTips::where('touzi', 'p-' . $dice['planet'])
//                    ->whereOr('touzi', 's-' . $dice['sign'])
//                    ->whereOr('touzi', 'h-' . $dice['house'])
//                    ->select();
//
//                $dice_status = $this->diceStatus($dice['planet'], $dice['sign'], $dice['house'], $dice['deg']);
//
//                $result = [
//                    'did' => $dice['id'],
//                    'time' => $dice['create_time'],
//                    'planet' => $dice['planet'],
//                    'house' => $dice['house'],
//                    'sign' => $dice['sign'],
//                    'love_status' => $dice_status['love'],
////            'marital_status'=>$dice_status['marital'],
//                    'health_status' => $dice_status['health'],
//                    'trip_status' => $dice_status['trip'],
//                    'money_status' => $dice_status['money'],
//                    'career_status' => $dice_status['career'],
//                    'study_status' => $dice_status['study'],
//                ];
//
//                foreach ($tips as $tip)
//                {
//                    if ($tip['touzi'] == 'p-' . $dice['planet']) $result['planet_text'] = $tip['text'];
//                    if ($tip['touzi'] == 's-' . $dice['sign']) $result['sign_text'] = $tip['text'];
//                    if ($tip['touzi'] == 'h-' . $dice['house']) $result['house_text'] = $tip['text'];
//                }
//
//                $result['url'] = 'https://weidian.com/item.html?itemID=2552906806';// 微店链接
//
//                return show(config('code.success'), '加载成功', $result);
//            }
//        }
//        catch (\Exception $e)
//        {
//            \think\Log::write('骰子经典模式查询失败' . $e->getMessage(), 'divination_error', true);
////            \think\Log::write('骰子经典模式查询失败' . var_export($e,true), 'divination_error_details', true);
//            return show(config('code.error'), '加载失败');
//        }
    }

    /**
     * 骰子吉凶
     * @param int $planet 行星id
     * @param int $sign 星座id
     * @param int $house 宫位id
     * @param float $deg 落星座度数
     * @return array
     */
    private function diceStatus($planet = null, $sign = null, $house = null, $deg = null)
    {
        // 初始化
        $score = [
            'love' => 0,
            'marital' => 0,
            'health' => 0,
            'trip' => 0,
            'money' => 0,
            'career' => 0,
            'study' => 0,
        ];
        // 计算行星得分
        switch ($planet)
        {
            case 0:
                $score['love'] += 4;
                $score['marital'] += 9;
                $score['health'] += 10;
                $score['trip'] += 10;
                $score['money'] += 2;
                $score['career'] += 10;
                $score['study'] += 10;
                break;
            case 1:
                $score['love'] += 5;
                $score['marital'] += 10;
                $score['health'] += -2;
                $score['trip'] += 1;
                $score['money'] += 8;
                $score['career'] += 3;
                $score['study'] += 1;
                break;
            case 2:
                $score['love'] += 2;
                $score['marital'] += 2;
                $score['health'] += 2;
                $score['trip'] += 9;
                $score['money'] += 1;
                $score['career'] += 2;
                $score['study'] += 9;
                break;
            case 3:
                $score['love'] += 10;
                $score['marital'] += 8;
                $score['health'] += 9;
                $score['trip'] += 9;
                $score['money'] += 10;
                $score['career'] += 4;
                $score['study'] += 9;
                break;
            case 4:
                $score['love'] += -5;
                $score['marital'] += -3;
                $score['health'] += -6;
                $score['trip'] += -8;
                $score['money'] += -5;
                $score['career'] += -3;
                $score['study'] += -8;
                break;
            case 5:
                $score['love'] += 8;
                $score['marital'] += 4;
                $score['health'] += 8;
                $score['trip'] += 10;
                $score['money'] += 9;
                $score['career'] += 10;
                $score['study'] += 10;
                break;
            case 6:
                $score['love'] += -10;
                $score['marital'] += 1;
                $score['health'] += -7;
                $score['trip'] += -3;
                $score['money'] += -7;
                $score['career'] += -4;
                $score['study'] += -3;
                break;
            case 7:
                $score['love'] += -10;
                $score['marital'] += -10;
                $score['health'] += -2;
                $score['trip'] += 5;
                $score['money'] += 5;
                $score['career'] += 1;
                $score['study'] += 5;
                break;
            case 8:
                $score['love'] += -8;
                $score['marital'] += -10;
                $score['health'] += -4;
                $score['trip'] += -2;
                $score['money'] += -6;
                $score['career'] += -10;
                $score['study'] += -2;
                break;
            case 9:
                $score['love'] += -6;
                $score['marital'] += -6;
                $score['health'] += -10;
                $score['trip'] += -4;
                $score['money'] += 6;
                $score['career'] += -7;
                $score['study'] += -4;
                break;
            case 12:
                $score['love'] += 9;
                $score['marital'] += 9;
                $score['health'] += 9;
                $score['trip'] += 9;
                $score['money'] += 9;
                $score['career'] += 9;
                $score['study'] += 9;
                break;
            case 16:
                $score['love'] -= 9;
                $score['marital'] -= 9;
                $score['health'] -= 9;
                $score['trip'] -= 9;
                $score['money'] -= 9;
                $score['career'] -= 9;
                $score['study'] -= 9;
                break;
        }
        // 庙+5，旺+4，三分+2，界+1，面+0.5，浮游时吉星【金木】+1.5，凶星【火土】-1.5，陷落-4
        $sign_score = 0;
        $is_change = false;
        if ($planet <= 9)
        {
            $ancient = config('astrolog.ancient')[$sign];// 古典数据

            if ($ancient[0] == $planet)
            {
                $sign_score += 5;// 入庙 +5
                $is_change = true;
            }
            if ($ancient[1] == $planet)
            {
                $sign_score += 4;// 擢升 旺 +4
                $is_change = true;
            }
            if (in_array($planet, $ancient[2]))
            {
                $sign_score += 2;// 三分 +2
                $is_change = true;
            }
            for ($i = 0; $i < 6; $i++)
            {
                if (
                    $planet &&
                    ($deg >= $ancient[3]['default'][1][$i]
                        && $deg < $ancient[3]['default'][1][$i + 1])
                )
                {
                    $sign_score += 2;// 界 +1
                    $is_change = true;
                }
            }
            if ($ancient[4][floor($deg / 10)] == $planet)
            {
                $sign_score += 0.5;// 面 +0.5
                $is_change = true;
            }
            $fall = ($sign <= 6) ? ($sign + 6) : ($sign - 6);
            $fall_ancient = config('astrolog.ancient')[$fall];
            if ($fall_ancient[0] == $planet)
            {
                $sign_score -= 5;// 失势 -4
                $is_change = true;
            }
            if ($fall_ancient[1] == $planet)
            {
                $sign_score -= 4;// 落陷 -4
                $is_change = true;
            }
            // 天王星  入庙 失势
            if ($planet == 7)
            {
                if ($sign == 11)
                {
                    $sign_score += 5;
                    $is_change = true;
                } elseif ($sign == 5)
                {
                    $sign_score -= 5;
                    $is_change = true;
                }
            }
            // 海王星  入庙 失势
            if ($planet == 8)
            {
                if ($sign == 12)
                {
                    $sign_score += 5;
                    $is_change = true;
                } elseif ($sign == 6)
                {
                    $sign_score -= 5;
                    $is_change = true;
                }
            }
            // 冥王星  入庙 失势
            if ($planet == 9)
            {
                if ($sign == 8)
                {
                    $sign_score += 5;
                    $is_change = true;
                } elseif ($sign == 2)
                {
                    $sign_score -= 5;
                    $is_change = true;
                }
            }
        }
        // 游走状态
        if ($is_change === false)
        {
            if ($planet == 3 || $planet == 5) $sign_score += 1.5;
            elseif ($planet == 4 || $planet == 6) $sign_score -= 1.5;
        }

        $score['love'] += $sign_score;
        $score['marital'] += $sign_score;
        $score['health'] += $sign_score;
        $score['trip'] += $sign_score;
        $score['money'] += $sign_score;
        $score['career'] += $sign_score;
        $score['study'] += $sign_score;

        switch ($house)
        {
            case 1:
                $score['love'] *= 1.5;
                $score['marital'] *= 1.5;
                $score['health'] *= 2;
                $score['trip'] *= 1.5;
                $score['money'] *= 1.5;
                $score['career'] *= 1.5;
                $score['study'] *= 1.5;
                break;
            case 2:
                $score['love'] *= 1;
                $score['marital'] *= 1;
                $score['health'] *= 1;
                $score['trip'] *= 1;
                $score['money'] *= 2;
                $score['career'] *= 1;
                $score['study'] *= 1;
                break;
            case 3:
                $score['love'] *= 1;
                $score['marital'] *= 1;
                $score['health'] *= 1;
                $score['trip'] *= 2;
                $score['money'] *= 1;
                $score['career'] *= 1;
                $score['study'] *= 2;
                break;
            case 4:
                $score['love'] *= 1.1;
                $score['marital'] *= 1.2;
                $score['health'] *= 1;
                $score['trip'] *= 1;
                $score['money'] *= 1.2;
                $score['career'] *= 1;
                $score['study'] *= 1;
                break;
            case 5:
                $score['love'] *= 2;
                $score['marital'] *= 1.1;
                $score['health'] += 5;
                $score['trip'] *= 1;
                $score['money'] *= 1.5;
                $score['career'] *= 1;
                $score['study'] *= 1;
                break;
            case 6:
                $score['love'] -= 15;
                $score['marital'] -= 15;
                $score['health'] *= 2;
                $score['trip'] -= 12;
                $score['money'] -= 10;
                $score['career'] *= 1.3;
                $score['study'] *= 1.3;
                break;
            case 7:
                $score['love'] *= 2;
                $score['marital'] *= 2;
                $score['health'] *= 1;
                $score['trip'] *= 1.5;
                $score['money'] *= 1;
                $score['career'] *= 1.2;
                $score['study'] *= 1;
                break;
            case 8:
                $score['love'] -= 15;
                $score['marital'] -= 15;
                $score['health'] -= 20;
                $score['trip'] -= 15;
                $score['money'] *= 1.5;
                $score['career'] -= 10;
                $score['study'] -= 10;
                break;
            case 9:
                $score['love'] *= 1;
                $score['marital'] *= 1;
                $score['health'] += 5;
                $score['trip'] *= 2;
                $score['money'] *= 1;
                $score['career'] *= 1.1;
                $score['study'] *= 2;
                break;
            case 10:
                $score['love'] *= 1;
                $score['marital'] *= 1;
                $score['health'] += 5;
                $score['trip'] *= 1;
                $score['money'] *= 1.2;
                $score['career'] *= 2;
                $score['study'] += 5;
                break;
            case 11:
                $score['love'] *= 1.1;
                $score['marital'] *= 1;
                $score['health'] *= 1;
                $score['trip'] *= 1.2;
                $score['money'] *= 1.3;
                $score['career'] *= 1.5;
                $score['study'] += 5;
                break;
            case 12:
                $score['love'] -= 20;
                $score['marital'] -= 20;
                $score['health'] -= 20;
                $score['trip'] -= 20;
                $score['money'] -= 20;
                $score['career'] -= 20;
                $score['study'] -= 20;
                break;
        }

        $result = [];
        foreach ($score as $k => $s)
        {
            if ($s < -25) $result[$k] = '凶';// 低于-25	凶
            elseif ($s >= -25 && $s < -15) $result[$k] = '不利';// 低于-15	不利
            elseif ($s >= -15 && $s < -5) $result[$k] = '不顺';// 低于-5	不顺
            elseif ($s >= -5 && $s < 5) $result[$k] = '平';// 低于5	平
            elseif ($s >= 5 && $s < 15) $result[$k] = '小吉';// 高于5	小吉
            elseif ($s >= 15 && $s < 25) $result[$k] = '吉';// 高于15	吉
            elseif ($s >= 25) $result[$k] = '大吉';// 高于25	大吉
        }
        return $result;
    }

    /**
     * @title 骰子专业模式
     * @method GET
     * @return Json
     * @return \think\Response|\think\response\Json|\think\response\Jsonp|\think\response\Redirect|\think\response\Xml
     * @readme /doc/md/divination/specialty.md
     */
    public function specialty()
    {
        $did = input('did/d');
        $uid = (int)($this->user['id']);

        if ($did <= 0 || $uid <= 0)
        {
            return show(config('code.error'), '参数错误');
        }

        try
        {
            $is_use_cache = 1;
            if ($is_use_cache)
            {
                $specialty = (new Divination())->getDetails([0 => $did])[0];
                $divination_deg = ($specialty['sign'] - 1) * 30 + $specialty['deg'];// 骰子度数
                $sabien_text = (new DivinationSabienTips())->getDetail(['sign' => $specialty['sign'], 'deg' => floor($specialty['deg'])]);
            } else
            {
                $specialty = Divination::field('id,question,planet,sign,house,deg,create_time,timezone')->where('uid', $uid)
                    ->find($did);
                $divination_deg = ($specialty['sign'] - 1) * 30 + $specialty['deg'];// 骰子度数
                $sabien_text = Db::table('wechat_backup_07_18_14_43_00.app_sabien')->field('text')
                    ->where('sign_deg', $specialty['sign'] . '-' . floor($specialty['deg']))
                    ->find();
            }

        }
        catch (\Exception $e)
        {
            Log::write('骰子专业模式查询失败' . $e->getMessage(), 'divination_error', true);
            return show(config('code.error'), '加载失败');
        }

        if (!$specialty || $specialty['uid'] != $uid)
        {
            return show(config('code.error'), '数据不存在');
        }

        $details = [
            'did' => $did,
            'divination' => [
                'id' => $specialty['planet'],
                'deg' => $divination_deg,
                'in_sign_id' => $specialty['sign'],
                'in_sign_deg' => in_sign_deg($divination_deg),
                'in_sign_deg_e' => floatval($specialty['deg']),
                'in_house_id' => $specialty['house'],
                'ancient' => $this->get_ancient_status($specialty['planet'], $specialty['sign'], floatval($specialty['deg'])),
                'sabien' => $sabien_text['text'],

            ],
        ];
        // 12宫宫头度数【整宫制】
        $asc_sign = (int)(ceil($divination_deg / 30) + 12 - $specialty['house'] * 1);
        if ($asc_sign > 12) $asc_sign -= 12;
        elseif ($asc_sign < 0) $asc_sign += 12;
        $asc = $asc_sign * 30;
        for ($i = 0; $i <= 11; $i++)
        {
            $deg = $asc + 30 * $i;
            if ($deg >= 360) $deg = $deg - 360;
            $details['house'][$i + 1] = [
                'deg' => $deg,
                'in_sign_id' => $deg / 30 + 1,
                'in_sign_deg' => 0,
            ];
        }
        // 格林尼治时间
        $truetime = get_base_time($specialty['create_time'], floor($specialty['timezone']));

        $utdatenow = strftime("%d.%m.%Y", $truetime);
        $utnow = strftime("%H:%M:%S", $truetime);

        $asps_display = [0, 60, 90, 120, 180];
        $asp_orb = [0 => 2, 60 => 1, 90 => 2, 120 => 2, 180 => 2];// 2 1 2 2 2

        // 求出当前天象的日月水金火木土天海冥的黄经度数
        $exec_str = config('astrolog.prefix') . " -b{$utdatenow} -ut{$utnow} -p0123456789 -eswe -fl -head";

        exec($exec_str, $out);

        $now_planet = [];

        foreach ($out as $o) $now_planet[] = $o * 1;
        // 检测是否成相
        $details['planets'] = null;
        $details['divination']['phase'] = null;
        foreach ($now_planet as $k => $p2)
        {
            $da = abs($p2 - $divination_deg);
            if ($da > 180) $da = 360 - $da;
            foreach ($asps_display as $asp)
            {
                $asp_orb_deg = abs($da - $asp);
                $or_orb = $asp_orb[$asp];
                if ($asp_orb_deg <= $or_orb)
                {
                    $phase = [
                        'id1' => $specialty['planet'],
                        'id2' => $k,
                        'phase_e' => $asp,
                        'phase_orb' => $asp_orb_deg,
                        'phase_or_orb' => $or_orb,
                    ];
                    $details['divination']['phase'][] = $phase;
                    // 记录天象行星信息
                    $p2_in_sign_id = ceil($p2 / 30);
                    $p2_in_sign_id_e = $p2 - ($p2_in_sign_id - 1) * 30;
                    $p2_in_house_id = null;
                    foreach ($details['house'] as $h => $dh)
                    {
                        if ($p2 >= $dh['deg'] && $p2 < $dh['in_sign_id'] * 30) $p2_in_house_id = $h;
                    }
                    $details['planets'][] = [
                        'id' => $k,
                        'deg' => $p2,
                        'in_sign_id' => $p2_in_sign_id,
                        'in_sign_deg' => in_sign_deg($p2),
                        'in_sign_deg_e' => $p2_in_sign_id_e,
                        'in_house_id' => $p2_in_house_id,
                        'ancient' => $this->get_ancient_status($k, $p2_in_sign_id, $p2_in_sign_id_e),
                        'phase' => [$phase],
                    ];
                }
            }
        }

        return show(config('code.success'), '成功', $details);
    }

    /**
     * 获取行星古典七段势力状态
     * @param null $planet
     * @param null $sign
     * @param float $deg
     * @return array|null
     */
    private function get_ancient_status($planet = null, $sign = null, $deg = 0.0)
    {
        // 非古典七星落座位置也有该位置庙旺弱陷界十度信息
        if ($planet === null || $planet < 0 || $sign === null) return null;
        $ret = [
            'power' => 0,
            'walls' => -1, 'walls_cn' => '',// 庙
            'promote' => -1, 'promote_cn' => '',// 旺
            'trisection' => -1, 'trisection_cn' => '',// 三分
            'extent' => -1, 'extent_cn' => '',// 界
            'period' => -1, 'period_cn' => '',// 面
            'migration' => -1, 'migration_cn' => '',// 游走
            'or_extent_planet_id' => -1, 'or_period_planet_id' => -1,
        ];

        $fall = ($sign <= 6) ? ($sign + 6) : ($sign - 6);

        $config_ancient = config('astrolog.ancient')[$sign];
        $config_ancient_fall = config('astrolog.ancient')[$fall];

        // 入庙
        if ($planet < 7 && $config_ancient[0] == $planet)
        {
            $ret['power'] += 5;
            $ret['walls'] = 1;
            $ret['walls_cn'] = '入庙';
        } elseif ($planet < 7 && $config_ancient_fall[0] == $planet)
        {
            $ret['power'] -= 5;
            $ret['walls'] = 2;
            $ret['walls_cn'] = '失势';
        }

        // 天王星  入庙 失势
        if ($planet == 7)
        {
            if ($sign == 11)
            {
                $ret['power'] += 5;
                $ret['walls'] = 1;
                $ret['walls_cn'] = '入庙';
            } elseif ($sign == 5)
            {
                $ret['power'] -= 5;
                $ret['walls'] = 2;
                $ret['walls_cn'] = '失势';
            }
        }
        // 海王星  入庙 失势
        if ($planet == 8)
        {
            if ($sign == 12)
            {
                $ret['power'] += 5;
                $ret['walls'] = 1;
                $ret['walls_cn'] = '入庙';
            } elseif ($sign == 6)
            {
                $ret['power'] -= 5;
                $ret['walls'] = 2;
                $ret['walls_cn'] = '失势';
            }
        }
        // 冥王星  入庙 失势
        if ($planet == 9)
        {
            if ($sign == 8)
            {
                $ret['power'] += 5;
                $ret['walls'] = 1;
                $ret['walls_cn'] = '入庙';
            } elseif ($sign == 2)
            {
                $ret['power'] -= 5;
                $ret['walls'] = 2;
                $ret['walls_cn'] = '失势';
            }
        }
        // 擢升
        if ($config_ancient[1] !== '' && $config_ancient[1] == $planet)
        {
            $ret['power'] += 4;
            $ret['promote'] = 1;
            $ret['promote_cn'] = '擢升';
        } elseif ($config_ancient_fall[1] !== '' && $config_ancient_fall[1] == $planet)
        {
            $ret['power'] -= 4;
            $ret['promote'] = 2;
            $ret['promote_cn'] = '落陷';
        }
        // 三分
        if (in_array($planet, $config_ancient[2]))
        {
            $ret['power'] += 3;
            $ret['trisection'] = 1;
            $ret['trisection_cn'] = '三分';
        }
        // 界主 界主为1 +2
//        if (session('xzns.extent') == 'ptolemy_world')
//            $extent = $config_ancient[3]['ptolemy_world'];
//        else
        // 使用埃及界
        $extent = $config_ancient[3]['default'];

        for ($i = 0; $i < 5; $i++)
        {
            if ($deg > $extent[1][$i] && $deg < $extent[1][$i + 1])
            {
                if ($extent[0][$i] == $planet)
                {
                    $ret['power'] += 2;
                    $ret['extent'] = 1;
                    $ret['extent_cn'] = '界主';
                }
                $ret['or_extent_planet_id'] = $extent[0][$i];
            }
        }
        // 旬主或十度
        for ($i = 0; $i < 3; $i++)
        {
            $min = $i * 10;
            $max = $min + 10;
            if ($deg > $min && $deg < $max)
            {
                if ($config_ancient[4][$i] == $planet)
                {
                    $ret['power'] += 1;
                    $ret['period'] = 1;
                    $ret['period_cn'] = '旬主';
                }
                $ret['or_period_planet_id'] = $config_ancient[4][$i];
            }
        }

        if ($ret['walls'] == -1 && $ret['promote'] == -1 && $ret['trisection'] == -1 && $ret['extent'] == -1 && $ret['period'] == -1 && $ret['power'] == 0 && $planet < 7)
        {
            $ret['power'] = -5;
            $ret['migration'] = 1;
            $ret['migration_cn'] = '游走';
        }
        if ($planet > 6 && $planet < 9 && $ret['walls'] == -1)
        {
            $ret['power'] = -5;
            $ret['migration'] = 1;
            $ret['migration_cn'] = '游走';
        }

        return $ret;
    }

    /**
     * @title 卜卦模式
     * @method GET
     * @readme /doc/md/divination/divination.md
     * @return \think\Response|\think\response\Json|\think\response\Jsonp|\think\response\Redirect|\think\response\Xml
     */
    public function divination()
    {
        $did = input('did/d', 0);
        $uid = $this->user['id'];
        $tid = input('tid/d', 1);

        // 星盘配置方案使用默认值
        if (!in_array($tid, [1, 2, 3], true))
        {
            $tid = 1;
        }

        try
        {
            $divination = (new Divination())->getDetails([0 => $did])[0];
            $divination_note_count = (new DivinationNote())->getCountAll(['uid' => $uid, 'did' => $did]);
        }
        catch (\Exception $e)
        {
            Log::write('骰子卜卦模式查询失败：' . $e->getMessage(), 'divination_error', true);
            return show(config('code.error'), '加载失败');
        }
        if (!$divination || $divination['uid'] != $uid)
        {
            return show(config('code.error'), '数据不存在');
        }
        // 调试提问信息错误的数据
        if (!isset($divination['longitude']) || !$divination['longitude'])
        {
            Log::write('$divination = ' . var_export($divination, true), 'info', true);
            return show(config('code.error'), '服务异常，请稍后再试!');
        }

        $settingData = (new AstroSettingUser1751())->getUserSettingByTid(['uid' => $this->user['id'], 'tid' => $tid, 'chart' => 'divination']);

        $Astrolog = Astrolog::getInstance();

        if (!empty($settingData))
        {
            $userSetting = ['divination' => $settingData];
        } else
        {
            $userSetting = config('astroset.setting1');
        }

        // 界主星参数数字转为字符串
        if (isset($userSetting['divination']['bound_type']))
        {
            if ($userSetting['divination']['bound_type'] === 0)
            {
                $userSetting['divination']['bound_type'] = 'default';
            } else
            {
                $userSetting['divination']['bound_type'] = 'ptolemy_world';
            }
        }

        $advanceInfo = [
            'year' => date('Y', $divination['create_time']) * 1,
            'month' => date('m', $divination['create_time']) * 1,
            'day' => date('d', $divination['create_time']) * 1,
            'hour' => date('H', $divination['create_time']) * 1,
            'minute' => date('i', $divination['create_time']) * 1,
            'timezone' => $divination['timezone'] * 1,
            'is_summer' => 0,
            'longitude' => $divination['longitude'],
            'latitude' => $divination['latitude']
        ];
        $Astrolog->setAdvance($advanceInfo)
            ->setExecPrefix(config('astrolog.prefix'))
            ->setIsAstrolabe(true);
        // 较低版本时，没有version，增加判断
        $rec = Util::CheckAppVersion('1.9.0');
        if (isset($this->headers['version']))
        {
            if ($rec === '大' || $rec === '同')
            {
                $Astrolog->setVersion(2);
            }
        }

        $details = $Astrolog->setUserSetting($userSetting)
            ->setGetDatas(['divination'])
            ->getAstroDatas()
            ->getDatas('divination');

        $details['note_count'] = $divination_note_count;

        return show(config('code.success'), '成功', $details);
    }

    /**
     * 参数规则
     * @name 字段名称
     * @type 类型
     * @require 是否必须
     * @default 默认值
     * @desc 说明
     * @range 范围
     * @return array
     */
    public static function getRules()
    {
        $rules = [
            'get' => [
                'access_token' => ['name' => 'access_token', 'type' => 'string', 'require' => 'true', 'default' => '无', 'desc' => '接口访问凭证', 'range' => '32位',],
                'ucid' => ['name' => 'ucid', 'type' => 'string', 'require' => 'true', 'default' => '无', 'desc' => '用户ucid', 'range' => '32位',],
                'question' => ['name' => 'question', 'type' => 'string', 'require' => 'true', 'default' => '无', 'desc' => '问题', 'range' => '30字以内',],
                'timezone' => ['name' => 'timezone', 'type' => 'float', 'require' => 'true', 'default' => '无', 'desc' => '时区', 'range' => '-12～12',],
            ],
            'history' => [
                'access_token' => ['name' => 'access_token', 'type' => 'string', 'require' => 'true', 'default' => '无', 'desc' => '接口访问凭证', 'range' => '32位',],
                'ucid' => ['name' => 'ucid', 'type' => 'string', 'require' => 'true', 'default' => '无', 'desc' => '用户ucid', 'range' => '32位',],
                'page' => ['name' => 'page', 'type' => 'int', 'require' => 'false', 'default' => '1', 'desc' => '分页页码', 'range' => '不限',],
            ],
            'delete' => [
                'access_token' => ['name' => 'access_token', 'type' => 'string', 'require' => 'true', 'default' => '无', 'desc' => '接口访问凭证', 'range' => '32位',],
                'ucid' => ['name' => 'ucid', 'type' => 'string', 'require' => 'true', 'default' => '无', 'desc' => '用户ucid', 'range' => '32位',],
                'did' => ['name' => 'did', 'type' => 'int', 'require' => 'true', 'default' => '无', 'desc' => '提问id', 'range' => '',],
            ],
            'dice' => [
                'access_token' => ['name' => 'access_token', 'type' => 'string', 'require' => 'true', 'default' => '无', 'desc' => '接口访问凭证', 'range' => '32位',],
                'ucid' => ['name' => 'ucid', 'type' => 'string', 'require' => 'true', 'default' => '无', 'desc' => '用户ucid', 'range' => '32位',],
                'did' => ['name' => 'did', 'type' => 'int', 'require' => 'true', 'default' => '无', 'desc' => '骰子id', 'range' => '不限',],
            ],
            'specialty' => [
                'access_token' => ['name' => 'access_token', 'type' => 'string', 'require' => 'true', 'default' => '无', 'desc' => '接口访问凭证', 'range' => '32位',],
                'ucid' => ['name' => 'ucid', 'type' => 'string', 'require' => 'true', 'default' => '无', 'desc' => '用户ucid', 'range' => '32位',],
                'did' => ['name' => 'did', 'type' => 'int', 'require' => 'true', 'default' => '无', 'desc' => '骰子id', 'range' => '不限',],
            ],
            'divination' => [
                'access_token' => ['name' => 'access_token', 'type' => 'string', 'require' => 'true', 'default' => '无', 'desc' => '接口访问凭证', 'range' => '32位',],
                'ucid' => ['name' => 'ucid', 'type' => 'string', 'require' => 'true', 'default' => '无', 'desc' => '用户ucid', 'range' => '32位',],
                'did' => ['name' => 'did', 'type' => 'int', 'require' => 'true', 'default' => '无', 'desc' => '骰子id', 'range' => '不限',],
                'tid' => ['name' => 'tid', 'type' => 'int', 'require' => 'true', 'default' => '1', 'desc' => '卜卦盘配置方案id', 'range' => '1～3',],
            ],
        ];
        return $rules;
    }
}
